//////////////////////////////////////////////////
// glShaderProgram.h
//
// Author: Tarik Belabbas et Adrien Hoffer
//////////////////////////////////////////////////

#ifndef GLSHADERPROGRAM_H_
#define GLSHADERPROGRAM_H_

#define GL_GLEXT_PROTOTYPES

#include <GL/gl.h>
#include <string>
#include <map>

struct glSShaderObject
{
	glSShaderObject()
	{
		m_shader = 0;
	}

	GLuint m_shader;
	GLenum m_shaderType;
};

class glShaderProgram
{
public:
	glShaderProgram					();
	~glShaderProgram				();

	GLboolean	initialize			( const char* _vertexPath,
										const char* _fragmentPath = NULL,
										const char* _geometryPath = NULL );
	void		unload				();

	bool		linkProgram			();
	void		useProgram			();
	void		unuseProgram		();

	GLuint		getUniformLocation	( const char* _name );
	GLuint		getAttribLocation	( const char* _name );

	void		sendUniform			( const char* _name, const float* _matrix,
										bool _transpose = false );
	void		sendUniform			( const char* _name, float _uniform );
	void		sendUniform			( const char* _name, int _uniform );
	void		sendUniform			( const char* _name, glm::vec3 _uniform );
	void		bindAttribute		( unsigned int _index,
										const char* _attribName );

	void		transformFeedbackVaryings	( GLsizei _count,
								const GLchar** _varyings, GLenum _bufferMode);

	GLuint		getProgramName		()	const	{ return m_program; }

private:
	bool		loadShader			( glSShaderObject& _shader,
										const char* _shaderPath );
	void		unloadShader		( GLuint& _shader );

	// Members
	GLuint			m_program;

	glSShaderObject	m_vertexShader;
	glSShaderObject	m_fragmentShader;
	glSShaderObject	m_geometryShader;

	std::map< std::string, GLuint > m_uniformMap;
	std::map< std::string, GLuint > m_attribMap;
};

#endif /* GLSHADERPROGRAM_H_ */
